import {esri} from "../api/esriAPI";

/**
 * 图层逻辑操作-----------业务开发中，不允许直接调用它，如果需要，需要通过工具中向外提供接口
 * @class
 * */
export const ManageLayer = class {
  _uniqueIdMapConfig = new Map();//uniqueId和配置项的映射-----------理解为所有的图层的‘配置项’
  _uniqueIdMapLayer = new Map();//uniqueId和layer的映射-------------理解为已加载的图层
  _graphicLyaerMap = new Map();//用于记录和存储已经创建的GraphicLayer
  _manageView = null;//View的对象
  /**
   * 构造函数
   */
  constructor(manageView) {
    this._manageView = manageView;
  }

  /********************************************************************************************/
  /*                                                                                          */
  /*                                     对图层的各类操作                                  */
  /*                                                                                          */

  /********************************************************************************************/

  /**
   * 根据uniqueId获得对应的Layer对象，如果没有加载，但是存在于配置项中，会根据配置项加载该图层，并返回
   * @param {String} map  arcgis的Map对象
   * @param {String} uniqueId  唯一识别的id
   */
  getLayerByUniqueId(uniqueId) {
    let layer = null;
    if (this._uniqueIdMapLayer.has(uniqueId)) {
      layer = this._uniqueIdMapLayer.get(uniqueId);
      return layer;
    }
    if (!this._uniqueIdMapConfig.has(uniqueId)) {
      console.error("获得图层（" + uniqueId + "）出错了，不存在该配置项");
      return;
    }
    let config = this._uniqueIdMapConfig.get(uniqueId);
    //如果存在的配置项，只是父图层的索引，将直接获得父图层的配置项
    if (typeof config == "string") {
      config = this._uniqueIdMapConfig.get(config);
    }
    config.visible = true;
    layer = this.applyLayer(config);
    //将图层添加到地图中
    this._addToLayers(layer);
    layer = this._uniqueIdMapLayer.get(uniqueId);//避免MapImageLayer得到的不是对应的子图层
    layer.visible = true
    return layer;
  }

  /**
   * 根据uniqueId获得图层的类型
   * @param uniqueId
   * @returns {*}
   */
  getLayerTypeByUniqueId(uniqueId){
    if (!this._uniqueIdMapConfig.has(uniqueId)) {
      console.error("获得图层（" + uniqueId + "）出错了，不存在该配置项");
      return;
    }
    let config = this._uniqueIdMapConfig.get(uniqueId);
    //如果存在的配置项，只是父图层的索引，将直接获得父图层的配置项
    if (typeof config == "string") {
      config = this._uniqueIdMapConfig.get(config);
    }
    return config["uniqueType"]
  }

  /**
   * 多个图层切换
   * @param {String} uniqueIds  唯一识别的id的数组
   * @param {Boolean} visible  是否显示
   */
  switchLayers(uniqueIds, visible) {
    for (let uniqueId of uniqueIds) {
      this.switchLayer(uniqueId, visible)
    }
  }

  /**
   * 单个图层切换
   * @param {String} uniqueId  唯一识别的id
   * @param {Boolean} visible  是否显示
   */
  switchLayer(uniqueId, visible) {
    //TODO 却换中，是否需要改变图层的优先级，有待商讨
    if (this._uniqueIdMapLayer.has(uniqueId)) {
      let layer = this._uniqueIdMapLayer.get(uniqueId);
      layer.visible = visible
      return;
    }
    //如果该图层是隐藏，同时没有加载，处于配置项的状态，将不做处理
    if (visible) {
      let layer = this.getLayerByUniqueId(uniqueId);
      layer && (layer.visible = true);
    }
  }


  removeLayer(uniqueId) {
    let layer = this.getLayerByUniqueId(uniqueId);
    if (!layer) {
      console.error("不存在该图层", uniqueId);
    }
    let map = this._manageView.getMap()
    map && map.remove(layer);
  }

  /********************************************************************************************/
  /*                                                                                          */
  /*                                     根据url申请图层                                  */
  /*                                                                                          */

  /********************************************************************************************/
  applyLayerByUrl(uniqueId, uniqueType, url) {
    return this.applyLayer({uniqueId, uniqueType, url})
  }

  applyTileLayerByUrl(uniqueId, url) {
    return this.applyTileLayer({uniqueId, url})
  }

  applyFeatureLayerByUrl(uniqueId, url) {
    return this.applyFeatureLayer({uniqueId, url})
  }

  applyMapImageLayerByUrl(uniqueId, url) {
    return this.applyMapImageLayer({uniqueId, url})
  }

  applyElevationLayerByUrl(uniqueId, url) {
    return this.applyElevationLayer({uniqueId, url})
  }

  /********************************************************************************************/
  /*                                                                                          */
  /*                                     根据config申请图层                                  */
  /*                                                                                          */

  /********************************************************************************************/

  /**
   * 懒加载图层的配置项，为了更高的性能，为后期配置化，做准备
   * @param {String} map  arcgis的Map对象
   * @param {Array} configs  配置项的数组
   */
  lazyLoadingLayer(configs) {
    for (let config of configs) {
      let {visible, uniqueType, uniqueId, sublayers} = config;
      //图层：visible:true，或者不设置visible的话----直接加载
      if (typeof visible == "undefined" || visible) {
        let layer = this.applyLayer(config);
        //将图层添加到地图中
        this._addToLayers(layer);
      } else {//父图层的visible:false的情况----实行懒加载
        //是MapImageLayer类型，同时配置了sublayers
        if (uniqueType == "MapImageLayer" && sublayers) {
          for (let sublayer of sublayers) {
            //针对MapImageLayer类型，如果父图层是隐藏的状态，那么所有的子图层都将被改成隐藏状态
            sublayer.visible = visible && sublayer.visible;
            if (this._uniqueIdMapConfig.has(sublayer.uniqueId)) {
              console.error("存在该配置项了，请检查是否有误", sublayer.uniqueId);
            } else {
              //为了节约存储，只保存父图层的映射索引
              this._uniqueIdMapConfig.set(sublayer.uniqueId, uniqueId);
            }
          }
        }
        if (this._uniqueIdMapConfig.has(uniqueId)) {
          console.error("存在该配置项了，请检查是否有误", uniqueId);
        } else {
          //保存图层的映射索引
          this._uniqueIdMapConfig.set(uniqueId, config);
        }
      }
    }
  }

  /**
   * 加载各种类型的图层 ---------------- 不够需要自己扩展
   * @param {Object} config  配置项
   * @returns {Object} arcgis图层对象
   */
  applyLayer(config) {
    let {uniqueId, uniqueType} = config;
    //必须要有uniqueId
    if (!uniqueId) {
      console.error("没有配置uniqueId，不允许执行", uniqueId)
      return;
    }
    //判断是否支持该类型的加载
    if (!this["apply" + uniqueType]) {
      console.error("暂时不支持该类型的加载，如果需要自己扩展apply方法", uniqueType);
      return;
    }
    //加载不同类型的图层----例如：apply + TileLayer   =====>  applyTileLayer
    return this["apply" + uniqueType](config);
  }

  //MapImageLayer，允许显示和分析在一个地图服务定义层数据，输出图像代替特征。地图服务图像是根据请求动态生成的
  /**
   * 申请MapImageLayer图层
   * @param {Object} config  配置项
   * @returns {Object} arcgis图层对象
   */
  applyMapImageLayer(config) {
    let uniqueId = config.uniqueId;
    if (this._uniqueIdMapLayer.has(uniqueId)) {
      console.warn("已存在该图层，无法重新创建，请更改uniqueId,返回了已存在的图层", uniqueId);
      return this._uniqueIdMapLayer.get(uniqueId);
    }
    config.uniqueType = "MapImageLayer";
    let layer = new esri.MapImageLayer(config);
    //将图层添加到地图中
    this._addToLayers(layer);
    //子图层添加到已加载图层的管理器中
    var items = layer.allSublayers.items;//若没有配置sublayer，这里由于时机问题，将为undefine，满足我们要的情况
    for (let sublayer of items) {
      this._uniqueIdMapLayer.set(sublayer.uniqueId, sublayer);
      sublayer.uniqueType = "Sublayer";
      this._uniqueIdMapConfig.set(sublayer.uniqueId,sublayer)
    }
    this._uniqueIdMapLayer.set(uniqueId, layer);
    this._uniqueIdMapConfig.set(uniqueId,config)
    return layer;
  }

  //TileLayer，加载缓存地图服务的瓦片图层，缓存的服务访问缓存中的瓦片，而不是动态地绘制图像。由于缓存机制，所以渲染的速度比MapImageLayers快多了，适合叠加瓦片切图使用，而不是前端动态渲染的。
  //加载切片   http://map.geoq.cn/arcgis/rest/services/ChinaOnlineCommunity_Mobile/MapServer
  /**
   * 申请TileLayer图层
   * @param {Object} config 申请TileLayer的配置项.
   * @returns {Object} arcgis图层对象   如果该图层对象已被记录了，将提示报错信息
   */
  applyTileLayer(config) {
    let uniqueId = config.uniqueId;
    if (this._uniqueIdMapLayer.has(uniqueId)) {
      console.warn("已存在该图层，无法重新创建，请更改uniqueId,返回了已存在的图层", uniqueId);
      return this._uniqueIdMapLayer.get(uniqueId);
    }
    config.uniqueType = "TileLayer";
    let layer = new esri.TileLayer(config);
    //将图层添加到地图中
    this._addToLayers(layer);
    this._uniqueIdMapLayer.set(uniqueId, layer);
    this._uniqueIdMapConfig.set(uniqueId,config)
    return layer;
  }

  /**
   * 申请FeatureLayer图层
   * @param {Object} config 申请FeatureLayer的配置项.
   * @returns {Object} arcgis图层对象   如果该图层对象已被记录了，将提示报错信息
   */
  applyFeatureLayer(config) {
    let uniqueId = config.uniqueId;
    if (this._uniqueIdMapLayer.has(uniqueId)) {
      console.warn("已存在该图层，无法重新创建，请更改uniqueId,返回了已存在的图层", uniqueId);
      return this._uniqueIdMapLayer.get(uniqueId);
    }
    config.uniqueType = "FeatureLayer";
    let layer = new esri.FeatureLayer(config);
    //将图层添加到地图中
    this._addToLayers(layer);
    this._uniqueIdMapLayer.set(uniqueId, layer);
    this._uniqueIdMapConfig.set(uniqueId,config)
    return layer;
  }

  //SceneLayer,即为加载三维场景图层，应用在三维模式下显示。
  /**
   * 申请SceneLayer图层
   * @param {Object} config 申请SceneLayer的配置项.
   * @returns {Object} arcgis图层对象   如果该图层对象已被记录了，将提示报错信息
   */
  applySceneLayer(config) {
    let uniqueId = config.uniqueId;
    if (this._uniqueIdMapLayer.has(uniqueId)) {
      console.warn("已存在该图层，无法重新创建，请更改uniqueId,返回了已存在的图层", uniqueId);
      return this._uniqueIdMapLayer.get(uniqueId);
    }
    config.uniqueType = "SceneLayer";
    let layer = new esri.SceneLayer(config);
    //将图层添加到地图中
    this._addToLayers(layer);
    this._uniqueIdMapLayer.set(uniqueId, layer);
    this._uniqueIdMapConfig.set(uniqueId,config)
    return layer;
  }

//ElevationLayer,即为加载地形高程的图层，应用在三维模式下显示。
  /**
   * 申请ElevationLayer图层 -------------高程
   * @param {Object} config 申请ElevationLayer的配置项.
   * @returns {Object} arcgis图层对象   如果该图层对象已被记录了，将提示报错信息
   */
  applyElevationLayer(config) {
    let uniqueId = config.uniqueId;
    if (this._uniqueIdMapLayer.has(uniqueId)) {
      console.warn("已存在该图层，无法重新创建，请更改uniqueId,返回了已存在的图层", uniqueId);
      return this._uniqueIdMapLayer.get(uniqueId);
    }
    config.uniqueType = "ElevationLayer";
    let layer = new esri.ElevationLayer(config);
    //将高程图层添加到地图中
    this._addToGround(layer)
    this._uniqueIdMapLayer.set(uniqueId, layer);
    this._uniqueIdMapConfig.set(uniqueId,config)
    return layer;
  }

  /**
   * 申请GraphicsLayer图层（GraphicsLayer特殊处理，单独创建一个容器存储）
   * @param {String} key 唯一识别
   * @param {Object} config 申请GraphicsLayer的配置项.
   * @returns {Object} arcgis图层对象
   */
  applyGraphicsLayer(key, config) {
    if (this._graphicLyaerMap.has(key)) {
      return this._graphicLyaerMap.get(key);
    }
    let layer = new esri.GraphicsLayer(config);
    //将图层添加到地图中
    this._addToLayers(layer);
    this._graphicLyaerMap.set(key, layer);
    return layer;
  }

  _addToGround(layer) {
    this._manageView && this._manageView.getMap() && this._manageView.getMap().ground.layers.add(layer);
  }

  _addToLayers(layer) {
    this._manageView && this._manageView.getMap() && this._manageView.getMap().add(layer);
  }

}
